#include "TADComunicacion.h"



/*

  El Proceso Emisor enviara un paquete NIPC extendido con los siguientes valores espec�ficos:
  Type: 0 ( El 0 indica que el paquete es del tipo Handshake )
  Payload: El identificador del disco o nada si no es un disco.
*/

ent HandShakeEmisor(ent Sock,ent SoyDisco){
	TMensaje *Mensaje;
	TMensaje *OtroMensaje;
	ent bytesRec=0,largo;
	time_t tActual;
	struct tm* tiempoGenerico;
	char cad[50];
	char MensajeP[1100];
	tActual = time(NULL);
	tiempoGenerico = localtime(&tActual);
	strftime(cad, 50, "%H%M%S", tiempoGenerico);
	Mensaje=(TMensaje*)calloc(1,sizeof(TMensaje));
	memset(Mensaje->payload,'\0',1100);
	sprintf(Mensaje->idDescriptor,"%s%010i",cad,rand()); // OBTENGO ASUNTO RANDOM

	if(SoyDisco){
		strcpy(Mensaje->payload,"Don Disco"); // ESTE NOMBRE EN REALIDAD SE SACA DEL ARCHIVO DE CONFIGURACION
		Mensaje->payloadLength=strlen(Mensaje->payload);
	}
	else{
		Mensaje->payloadLength=0;
	}
	Mensaje->payloadDescriptor='0'; // TYPE CERO POR HANDSHAKE
	send(Sock,(void*)Mensaje,sizeof(struct TMensaje),0);  // ENVIO REQUEST DE HANDSHAKE
	free(Mensaje);
	OtroMensaje=(TMensaje*)calloc(1,sizeof(TMensaje));

	while(bytesRec<=0){
		bytesRec=recv(Sock,(void*)OtroMensaje,sizeof(struct TMensaje),0); // RECIBO RESPUESTA DE HANDSHAKE
	}
	largo=OtroMensaje->payloadLength;
	strcpy(MensajeP,OtroMensaje->payload);
	free(OtroMensaje);
	if(largo==0){
		//printf("HandShake realizado correctamente\n");
		return 1;
	}
	else{
		printf("No se pudo realizar el HandShake\nCodigo de Error:%s",MensajeP); //Voy a devolver cero en la funcion despues afuera cierro el socket,etc.
		return 0;
	}

}


/*El Proceso Receptor segun quien sea ( Si soy un Raid o no) debe  responder con un paquete NIPC
  con los siguientes valores espec�ficos:
  Type: 0 ( El 0 indica que el paquete es del tipo Handshake )
  Payload:
  Vac�o, por lo que Payload Length sera 0, en caso de que la conexi�n se correcta
  C�digo/Mensaje de error indicando que la negociaci�n fue fallida y el motivo de
  esto. Luego de enviar este paquete el Proceso RAID cierra la conexi�n.

*/


ent HandShakeReceptor(ent sock,ent cantDisp,ent SoyRaid,ent EstaP){  //Si es un Raid me enteresa saber si tengo un planificador entonces tengo variable EstaP


	ent Largo;
	ent bytesRec=0;
	TMensaje *TheirM,*MyM;

	char cad[50],desicion;
	ent  i, stime,n,u=0,pos=0;
	TheirM=(TMensaje*)calloc(1,sizeof(TMensaje));
	while(bytesRec<=0){
	  bytesRec=recv(sock, (void*)TheirM, sizeof(struct TMensaje), 0);  // RECIBO REQUEST
	}
	bytesRec= 0;
	MyM=(TMensaje*)calloc(1,sizeof(TMensaje));
	memset(MyM->payload,'\0',1100);
	strcpy(MyM->idDescriptor ,TheirM->idDescriptor);
	Largo= TheirM->payloadLength;
	free(TheirM);
	MyM->payloadDescriptor='0';
	if(SoyRaid){ // SOY UN RAID
		if(cantDisp < 10){
			if(Largo != 0){ //ES UN PLANIFICADOR QUIEN ME HABLA
				//TODO OKEY
				MyM->payloadLength= 0;
				send(sock,(void*)MyM,sizeof(struct TMensaje),0); //ENVIO RESPONSE
				free(MyM);
				return 1;
			}
			else{ //NO ES UN PLANIFICADOR QUIEN ME HABLA
				if(EstaP){//TENEMOS UN PLANIFICADOR
					//TODO OKEY
					MyM->payloadLength= 0;
					send(sock,(void*)MyM,sizeof(struct TMensaje),0); //ENVIO RESPONSE
					free(MyM);
					return 1;
				}
				else{// NO TENEMOS UN PLANIFICADOR
					strcpy(MyM->payload,"El RAID NO SE ENCUENTRA EN ESTADO ACTIVO\n");
					MyM->payloadLength=strlen("El RAID NO SE ENCUENTRA EN ESTADO ACTIVO\n");
					send(sock,(void*)MyM,sizeof(struct TMensaje),0); //ENVIO RESPONSE
					close(sock);
					free(MyM);
					return 0;
				}
			}
		}
		else{//TENEMOS MUCHOS DISPOSITIVOS

			strcpy(MyM->payload,"El RAID NO ADMITE MAS CONEXIONES\n");
			MyM->payloadLength=strlen("El RAID NO ADMITE MAS CONEXIONES\n");
			send(sock,(void*)MyM,sizeof(struct TMensaje),0); //ENVIO RESPONSE
			close(sock);
			free(MyM);
			return 0;
		}
	}
	else{ // NO SOY UN RAID
			//POR LO PRONTO VAMOS A ACEPTAR SIEMPRE PUESTO QUE NO VEO CASO ENTRE PPD Y PFS QUE FALLE
			MyM->payloadLength= 0;
			send(sock,(void*)MyM,sizeof(struct TMensaje),0); //ENVIO RESPONSE
			free(MyM);
			return 1;
	}


}

//FUNCION QUE ENVIA UN MENSAJE NIPC EXTENDIDO SIN ESPERAR RESPUESTA ( ASINCRONICAMENTE )
ent ComunicacionA(ent sock,char desc,char cadena[1100]){

	TMensaje *Mensaje;
	time_t tActual;
	struct tm* tiempoGenerico;
	char cad[50],respuesta2[1100];
	tActual = time(NULL);
	tiempoGenerico = localtime(&tActual);
	strftime(cad, 50, "%H%M%S", tiempoGenerico);
	Mensaje=(TMensaje*)calloc(1,sizeof(TMensaje));
	sprintf(Mensaje->idDescriptor,"%s%010i",cad,rand());
	Mensaje->payloadDescriptor = desc;
	Mensaje->payloadLength=(ent)strlen(cadena);
	strcpy(Mensaje->payload,cadena);
	send(sock,(void*)Mensaje,sizeof(TMensaje),0); //ENVIO CADENA
	printf("envie %s\n",Mensaje->payload);
	free(Mensaje);
	return 0;
}


/*
Funcion especifica del Raid para obtener el tipo y nombre de los dispositivos que se estan conectando

*/
TInfo *ObtenerNombre(ent sock){

	TMensaje *Mensaje,*OtroMensaje;
	char Tipo;
	ent bytesRec=0;
	time_t tActual;
	TInfo *Info=(TInfo*)calloc(1,sizeof(TInfo));
	struct tm* tiempoGenerico;
	char cad[50],desicion;
	ent  i, stime,n,u=0,pos=0;
	tActual = time(NULL);
	tiempoGenerico = localtime(&tActual);
	strftime(cad, 50, "%H%M%S", tiempoGenerico);
	Mensaje=(TMensaje*)calloc(1,sizeof(TMensaje));
	sprintf(Mensaje->idDescriptor,"%s%010i",cad,rand());
	Mensaje->payloadDescriptor='R';
	Mensaje->payloadLength=(ent)strlen("hola");
	strcpy(Mensaje->payload,"hola");
	printf("hasta aca llega\n");
	send(sock,(void*)Mensaje,sizeof(struct TMensaje),0); //ENVIO SALUDO "HOLA"
	printf("hasta aca no llega\n");
	free(Mensaje);
	OtroMensaje=(TMensaje*)calloc(1,sizeof(TMensaje));

	while(bytesRec<=0){
	  bytesRec=recv(sock, (void*)OtroMensaje, sizeof(struct TMensaje), 0);  // RECIBO REQUEST
	}

	strcpy(Info->Nombre,OtroMensaje->payload);
	Info->Tipo=OtroMensaje->payloadDescriptor;
	free(OtroMensaje);
	return Info;
}


/*

Funcion que entrega el nombre al pedido "ObtenerNombre()" del RAID usada por PPD y PFS

*/
ent Nombre(ent Sock,char nombre[20],char Tipo){ // "Tipo" es 'F' si PFS o 'P' si Planificador
	ent bytesRec= 0,valor;
	TMensaje *TheirM;
	TMensaje *MyM;

	TheirM=(TMensaje*)calloc(1,sizeof(TMensaje));

	while(bytesRec<=0){
		bytesRec=recv(Sock, (void*)TheirM, sizeof(struct TMensaje), 0);
	}

	if(!strcmp(TheirM->payload,"hola")){

		MyM=(TMensaje*)calloc(1,sizeof(TMensaje));
		strcpy(MyM->idDescriptor ,TheirM->idDescriptor);
		strcpy(MyM->payload,nombre);
		MyM->payloadLength=(ent)strlen(nombre);
		MyM->payloadDescriptor=Tipo;
		valor=send(Sock,(void*)MyM,sizeof(struct TMensaje),0);
		free(MyM);
	    free(TheirM);
	}
	return 0;
}



char *ComunicacionBlock(int32_t sock,char cadena1[20],char cadena2[20]){
	TMensaje *Mensaje1,*Mensaje2,*MensajeR1,*MensajeR2;
	int32_t bytesRec=-1;
	time_t tActual;
	char id1[16];
	char id2[16];
	struct tm* tiempoGenerico;
	char cad[50],*Respuesta;

	tActual = time(NULL);
	tiempoGenerico = localtime(&tActual);
	strftime(cad, 50, "%H%M%S", tiempoGenerico);

	Mensaje1=(TMensaje*)calloc(1,sizeof(TMensaje));

	sprintf(Mensaje1->idDescriptor,"%s%010i",cad,rand());
	memcpy(id1,Mensaje1->idDescriptor,16);
	strcpy(Mensaje1->payload,cadena1);
	Mensaje1->payloadLength= strlen(Mensaje1->payload);
	Mensaje1->payloadDescriptor = '0';
	send(sock,(void*)Mensaje1,sizeof(struct TMensaje),0);

	free(Mensaje1);

	tActual = time(NULL);
	tiempoGenerico = localtime(&tActual);
	strftime(cad, 50, "%H%M%S", tiempoGenerico);

	Mensaje2=(TMensaje*)calloc(1,sizeof(TMensaje));

	sprintf(Mensaje2->idDescriptor,"%s%010i",cad,rand());
	memcpy(id2,Mensaje2->idDescriptor,16);
	strcpy(Mensaje2->payload,cadena2);
	Mensaje2->payloadLength= strlen(Mensaje2->payload);
	Mensaje2->payloadDescriptor = '0';
	send(sock,(void*)Mensaje2,sizeof(struct TMensaje),0);

	free(Mensaje2);

	MensajeR1=(TMensaje*)calloc(1,sizeof(TMensaje));
	while(bytesRec<0){
		bytesRec=recv(sock, (void*)MensajeR1, sizeof(struct TMensaje), MSG_WAITALL);
	}
	if(bytesRec==0){
		printf("ERROR: No se pudo leer Sector.\n");
		exit(EXIT_FAILURE);
	}

	bytesRec = -1;
	MensajeR2=(TMensaje*)calloc(1,sizeof(TMensaje));
	while(bytesRec<0){
		bytesRec=recv(sock, (void*)MensajeR2, sizeof(struct TMensaje), MSG_WAITALL);
	}
	if(bytesRec==0){
		printf("ERROR: No se pudo leer Sector.\n");
		exit(EXIT_FAILURE);
	}
	Respuesta = malloc(1024);
	if(!strncmp(MensajeR1->idDescriptor,id1,16)){
		memcpy(Respuesta,MensajeR1->payload,512);
		memcpy(Respuesta+512,MensajeR2->payload,512);
	}

	else{
		memcpy(Respuesta,MensajeR2->payload,512);
		memcpy(Respuesta+512,MensajeR1->payload,512);
	}


	free(MensajeR1);
	free(MensajeR2);

	return Respuesta;
}



int Comunicacion(int sock,char desc,int32_t numSec,char cadena[512],char respuesta[1100]){

	TMensaje *Mensaje;
	int bytesRec=-1,i=0;
	int cant,n=0;
	int Flag=0,largo=0,largo1=0;
	TMensaje *OtroMensaje;
	time_t tActual;
	char peticion[1000];
	struct tm* tiempoGenerico;
	char cad[50];

	memset(peticion,'\0',1000);
	sprintf(peticion,"write(%d,",numSec);
	largo1=strlen(peticion);
	memcpy(peticion+largo1,cadena,512);
	memcpy(peticion+largo1+512,")",1);
	largo = largo1 +512+1;

	tActual = time(NULL);
	tiempoGenerico = localtime(&tActual);
	strftime(cad, 50, "%H%M%S", tiempoGenerico);
	Mensaje=(TMensaje*)calloc(1,sizeof(TMensaje));
	sprintf(Mensaje->idDescriptor,"%s%010i",cad,rand());

	Mensaje->payloadDescriptor = desc;
	Mensaje->payloadLength=largo;
	memcpy(Mensaje->payload,peticion,largo);
	bytesRec=send(sock,(void*)Mensaje,sizeof(TMensaje),0); //ENVIO CADENA
	free(Mensaje);

	bytesRec=-1;

	OtroMensaje=(TMensaje*)calloc(1,sizeof(TMensaje));
	while(bytesRec<0){
		bytesRec=recv(sock,(void*)OtroMensaje,sizeof(struct TMensaje),0); // RECIBO RESPUESTA
	}
	if(bytesRec==0)
		return 0;
	strcpy(respuesta,OtroMensaje->payload);
	free(OtroMensaje);
	respuesta[bytesRec]='\0';
	if(!strcmp(respuesta,"Ok"))
		return 1;
	else
		return 0;
}








